package com.jf.cloud.service.sysmanager.common.db;

import com.jf.cloud.service.sysmanager.common.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * SQL工具类
 * 
 * @author 程伟平 创建时间：2013-12-05 10:33:30
 */
public final class SqlUtil {

	/**
	 * 日志
	 */
	private static Log log = LogFactory.getLog(SqlUtil.class);

	/**
	 * 判断是否为包装类
	 * 
	 * @author 程伟平 创建时间：2013-12-05 10:33:30
	 */
	public static boolean isWrapClass(Class<?> clazz) {
		String clazzName = clazz.getName();
		// 字符串
		if ("java.lang.String".equals(clazzName)) {
			return true;
		}
		// 长整型
		else if ("java.lang.Long".equals(clazzName)) {
			return true;
		}
		// 整型
		else if ("java.lang.Integer".equals(clazzName)) {
			return true;
		}
		// 单精度浮点数
		else if ("java.lang.Float".equals(clazzName)) {
			return true;
		}
		// 双精度浮点数
		else if ("java.lang.Double".equals(clazzName)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断是否为实体类
	 * 
	 * @author 程伟平 创建时间：2013-12-05 10:33:30
	 */
	public static boolean isEntityClass(Class<?> clazz) {
		return clazz.isAnnotationPresent(Entity.class) && clazz.isAnnotationPresent(Table.class) ? true : false;
	}

	/**
	 * 实体类和数据表对应关系池
	 */
	private static final Map<String, String> TableNamePool = new HashMap<String, String>();

	/**
	 * 根据实体类获取数据表名称
	 * 
	 * @author 程伟平 创建时间：2013-03-13 09:27:12
	 */
	public static String getTableName(Class<?> clazz) {
		if (!isEntityClass(clazz)) {
			throw new IllegalArgumentException("非法的实体类【" + clazz + "】！");
		}
		String clazzName = clazz.getName(); // 实体类名称
		if (!TableNamePool.containsKey(clazzName)) {
			Table table = clazz.getAnnotation(Table.class);
			String tableName = table.name();
			TableNamePool.put(clazzName, tableName);
			log.info("实体类【" + clazzName + "】，数据表【" + tableName + "】。");
		}
		return TableNamePool.get(clazzName);
	}

	/**
	 * 实体类属性和数据表字段对应关系池
	 */
	private static final Map<String, String> ColumnNamePool = new HashMap<String, String>();

	/**
	 * 根据实体类属性获取数据表字段名称
	 * 
	 * @author 程伟平 创建时间：2013-03-13 09:27:12
	 */
	public static String getColumnName(Class<?> clazz, Field field) {
		if (!isEntityClass(clazz)) {
			throw new IllegalArgumentException("非法的实体类【" + clazz + "】！");
		}
		String fieldName = field.getName() + "@" + clazz.getName();
		if (!ColumnNamePool.containsKey(fieldName)) {
			Column column = field.getAnnotation(Column.class);
			String columnName = column.name();
			ColumnNamePool.put(fieldName, columnName);
			log.info("实体类属性【" + fieldName + "】，数据表字段【" + columnName + "】。");
		}
		return ColumnNamePool.get(fieldName);
	}

	/**
	 * 根据字段名称获取类名称
	 * 
	 * @author 程伟平 2012-01-10
	 */
	public static String getClassName(String str) {
		if (str == null || str.length() == 0) {
			return str;
		}
		StringBuffer sb = new StringBuffer();

		String[] words = str.split("_");
		for (String word : words) {
			// 首字母大写
			sb.append(word.substring(0, 1).toUpperCase());
			// 非首字母小写
			sb.append(word.substring(1).toLowerCase());
		}

		return sb.toString();
	}

	/**
	 * 根据字段名称获取对象名称
	 * 
	 * @author 程伟平 2012-01-10
	 */
	public static String getObjectName(String str) {
		if (str == null || str.length() == 0) {
			return str;
		}
		StringBuffer sb = new StringBuffer();

		String[] words = str.split("_");
		for (String word : words) {
			if (sb.length() == 0) {
				sb.append(word.toLowerCase());
			} else {
				// 首字母大写
				sb.append(word.substring(0, 1).toUpperCase());
				// 非首字母小写
				sb.append(word.substring(1).toLowerCase());
			}
		}

		return sb.toString();
	}

	/**
	 * 将数组（字符串或数值型）转换成SQL的IN字符串
	 * 
	 * @author 程伟平 创建时间：2014-05-06 17:50:30
	 */
	public static <T> String getInSql(T[] os) {
		StringBuffer sb = new StringBuffer();
		if (os != null && os.length > 0) {
			for (Object o : os) {
				if (sb.length() > 0) {
					sb.append(",");
				}
				// 字符串
				if (o instanceof String) {
					sb.append("'").append(o).append("'");
				} else {
					sb.append(o);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 将集合（字符串或数值型）转换成SQL的IN字符串
	 * 
	 * @author 程伟平 创建时间：2014-05-06 17:50:30
	 */
	public static <T> String getInSql(Collection<T> os) {
		StringBuffer sb = new StringBuffer();
		if (os != null && os.size() > 0) {
			for (Object o : os) {
				if (sb.length() > 0) {
					sb.append(",");
				}
				// 字符串
				if (o instanceof String) {
					sb.append("'").append(o).append("'");
				} else {
					sb.append(o);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 根据分页数据SQL获取分页总记录数SQL
	 * 
	 * @author 程伟平 创建时间：2014-09-09 16:27:12
	 */
	public static String getPageCountSQL(String sql) {
		if (sql == null || !containsIgnoreCase(sql, "SELECT")) {
			throw new IllegalArgumentException("根据分页数据SQL获取分页总记录数SQL参数错误！参数sql不能为空且只能为查询SQL！");
		}
		if (StringUtil.notNull(sql) && isUniqueIgnoreCase(sql, "SELECT") && isUniqueIgnoreCase(sql, "FROM ") && !containsIgnoreCase(sql, "GROUP BY")) {
			// 普通查询解析
			int index = sql.toUpperCase().indexOf("FROM ");
			if (index > -1) {
				// 若有排序，去掉 ORDER BY 语句
				int orderIndex = sql.toUpperCase().indexOf("ORDER BY");
				if (orderIndex > -1) {
					return "SELECT COUNT(0) " + sql.substring(index, orderIndex);
				}
				return "SELECT COUNT(0) " + sql.substring(index);
			}
		}
		return "SELECT COUNT(0) FROM ( " + sql + " ) T";
	}

	/**
	 * 判断SQL语句中是否包含指定SQL关键字
	 * 
	 * @author 程伟平 创建时间：2014-09-10 10:08:37
	 */
	private static boolean containsIgnoreCase(String sql, String word) {
		if (sql == null || word == null) {
			throw new IllegalArgumentException("判断SQL语句中是否包含指定关键字参数错误！参数sql和word不能为空！");
		}
		return sql.toUpperCase().contains(word.toUpperCase());
	}

	/**
	 * 判断SQL语句中包含的SQL关键字是否唯一
	 * 
	 * @author 程伟平 创建时间：2014-09-10 10:08:37
	 */
	private static boolean isUniqueIgnoreCase(String sql, String word) {
		if (sql == null || word == null) {
			throw new IllegalArgumentException("判断SQL语句中包含的SQL关键字是否唯一参数错误！参数sql和word不能为空！");
		}
		sql = sql.toUpperCase(); // SQL语句转换为大写
		word = word.toUpperCase(); // SQL关键字转换为大写
		return sql.indexOf(word) > -1 && sql.indexOf(word) == sql.lastIndexOf(word);
	}

}
